#pragma once
#include <iostream>
#include <queue>
#include <pthread.h>//这个属于用户层面的库，但是结合了linux提供的轻量化进程，属于半用户半系统层，linux系统一般默认支持
using namespace std;

template<class T>
class BlockQueue
{
    static const int defaultnum=20;
public:
    BlockQueue(int maxsize=defaultnum)
    :_maxsize(maxsize)
    {
        pthread_mutex_init(&_mutex,nullptr);
        pthread_cond_init(&_c_cond,nullptr);
        pthread_cond_init(&_p_cond,nullptr);
    }

    void push(const T& t)
    {
        //以下都属于临界资源所以需要加锁
        pthread_mutex_lock(&_mutex);
        while(_q.size()>=_maxsize)//如果超市满了就不能push，生产者需要去c队列排队（条件变量）
        {
            pthread_cond_wait(&_p_cond,&_mutex);//通过条件变量可以确保等待的线程是以排队的方式去申请锁，而不是杂乱无序的随机申请访问
        }

        _q.push(t);
        
        if(_q.size()>0)  pthread_cond_signal(&_c_cond);//条件变量队列的线程属于休眠，需要被特定条件唤醒。
        pthread_mutex_unlock(&_mutex);
    }

    T pop()
    {
        pthread_mutex_lock(&_mutex);
        while(_q.size()<=0)//
        {
            pthread_cond_wait(&_c_cond,&_mutex);
        }
        T t=_q.front();_q.pop();
        if(_q.size()<_maxsize)  pthread_cond_signal(&_p_cond);
        pthread_mutex_unlock(&_mutex);
        return t;
    }

    ~BlockQueue()
    {
        pthread_mutex_destroy(&_mutex);
        pthread_cond_destroy(&_c_cond);
        pthread_cond_destroy(&_p_cond);
    }


//这是一个生产者和消费者的简易模型
private:
    queue<T> _q;
    int _maxsize;
    pthread_mutex_t _mutex;
    pthread_cond_t _c_cond;
    pthread_cond_t _p_cond;
};


